package com.matrix.draft.sockettest.day12;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

public class NIOServer {

    public static int PORT = 8080;

    public static void main(String[] args) {
        try {
            // 准备Selector
            Selector selector = Selector.open();
            // 准备ServerSocketChannel
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.socket().bind(new InetSocketAddress(PORT));
            System.err.println("服务端已启动...");
            // serverSocketChannel注册到selector
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

            // 等待时间的发生
            while (true) {
                // int activeKeyCount = selector.select();
                // 看看selector是否在后台默默地捕捉所有活动事件
                // System.err.println("----------当前波活动事件数-----------:" + activeKeyCount);

                // 遍历所有事件
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> keysIterator = selectionKeys.iterator();
                while (keysIterator.hasNext()) {
                    SelectionKey k = keysIterator.next();
                    /** 如果是OP_ACCEPT事件 **/
                    if (k.isAcceptable()) {
                        System.err.println("可Accept事件发生了");
                        ServerSocketChannel channel = (ServerSocketChannel) k.channel();
                        SocketChannel socketChannel = channel.accept();
                        System.out.println("客户端" + socketChannel.hashCode() + "连接成功");
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(2048));
                    }
                    /** 如果是OP_READ事件 **/
                    else if (k.isReadable()) {
                        System.err.println("可读事件发生了");
                        SocketChannel channel = (SocketChannel) k.channel();
                        if (!channel.isConnected()) {
                            channel.close();
                        }
                        ByteBuffer buffer = (ByteBuffer) k.attachment();
                        int len = channel.read(buffer);
                        // 当读取完毕,关闭连接
                        if (len != -1) {
                            String message = new String(buffer.array(), 0, len, StandardCharsets.UTF_8);
                            System.out.println("接收到客户端" + channel.hashCode() + "的数据: " + message);
                            buffer.clear();
                        }
                        write(channel, "OK");
                    }
                    /** 如果是OP_CONNECT事件 **/
                    else if (k.isConnectable()) {
                        System.err.println("可连接事件发生了");
                    }
                    /** 如果是OP_WRITE事件 **/
                    else if (k.isWritable()) {
                        System.err.println("可写事件发生了");
                    }
                    // 每个事件处理完要从集合移除
                    keysIterator.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void write(SocketChannel channel, String msg) throws IOException {
        channel.write(ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8)));
    }
}
